package com.garlicts.framework.ioc;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.garlicts.framework.annotation.*;
import com.garlicts.framework.extension.Plugin;
import com.garlicts.framework.job.BaseJob;
import com.garlicts.framework.util.ScanPackageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.garlicts.framework.core.Initialization;
import com.garlicts.framework.core.InstanceFactory;
import com.garlicts.framework.core.BeanLoader;
import com.garlicts.framework.core.fault.InitializationError;

/**
 * 初始化相关 Bean 类
 *
 * @author 水木星辰
 * @since 1.0
 */
public class BeanContainerComponent{
	
	private static final Logger logger = LoggerFactory.getLogger(BeanContainerComponent.class);

	private static final BeanLoader beanLoader = InstanceFactory.getBeanLoader();
	
    /**
     * Bean Map（Bean的Class对应实例）
     */
    private static Map<Class<?>, Object> beanMap = new ConcurrentHashMap<Class<?>, Object>();

    static {

        try {

            List<String> packages = ScanPackageUtil.getScanPackages();

            for(String item : packages){

                // 获取应用包路径下所有的类
                List<Class<?>> classList = beanLoader.getBeanClassList(item);

                for (Class<?> cls : classList) {

                    // 注册Bean
                    registerBean(cls);

                    // 注册初始化类
                    registerInitializeData(cls);

                    registerIocInit(cls);

                    // 注册job
                    registerJob(cls);

                    // 注册plugin
                    registerPlugin(cls);

                }

            }

        } catch (Exception e) {
            throw new InitializationError("BeanContainerComponent初始化异常！", e);
        }
    }

    /**
     * 获取 Bean Map
     */
    public static Map<Class<?>, Object> getBeanMap() {
        return beanMap;
    }
    
    /**
     * 获取 Bean 实例
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(Class<T> cls) {
        if (!beanMap.containsKey(cls)) {
            throw new RuntimeException("无法根据类名获取实例！" + cls);
        }
        return (T) beanMap.get(cls);
    }

    /**
     * 设置 Bean 实例
     */
    public static void setBean(Class<?> cls, Object obj) {
        beanMap.put(cls, obj);
    }
    
    /**
     * 销毁容器的所有数据 
     */
    public static void destroy(){
    	beanMap.clear();
    }
    
    /**
     * <p>注册Bean</p>
     * 扫描带有Bean/Controller/Aspect注解的类，并注册到Bean容器
     */
    private static void registerBean(Class<?> cls){
    	
        if (cls.isAnnotationPresent(Bean.class) ||
                cls.isAnnotationPresent(Service.class) ||
                cls.isAnnotationPresent(Controller.class) ||
                cls.isAnnotationPresent(Aspect.class) ||
                cls.isAnnotationPresent(RpcService.class)) {
                // 创建 Bean 实例
                Object beanInstance;
				try {
					
					beanInstance = cls.newInstance();
					
	                // 将 Bean 实例放入 Bean Map 中（键为 Bean 类，值为 Bean 实例）
	                beanMap.put(cls, beanInstance);

	                logger.info("注册Bea：{}", cls.getName());
	                
				} catch (Exception e) {
					e.printStackTrace();
				}

            }
    	
    }
    
    /**
     * 注册初始化类 
     * 初始化类都实现InitializeData接口
     */
    public static void registerInitializeData(Class<?> cls){
    	
        if(Initialization.class.isAssignableFrom(cls) && !cls.equals(Initialization.class)){
        	Object initInstance;
			try {
				initInstance = cls.newInstance();
	        	beanMap.put(cls, initInstance);
	        	logger.info(new StringBuffer("注册初始化类：").append(cls.getName()).toString());
			} catch (Exception e) {
				e.printStackTrace();
			}

        }
        
    }

    /**
     * 注册Ioc组件
     */
    public static void registerIocInit(Class<?> cls){

        if(IocInit.class.isAssignableFrom(cls) && !cls.equals(IocInit.class)){
            try {
                Object o = cls.newInstance();
                beanMap.put(cls, o);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 注册plugin
     */
    public static void registerPlugin(Class<?> cls){

        if(Plugin.class.isAssignableFrom(cls) && !cls.equals(Plugin.class)){
            Object pluginInstance;
            try {
                pluginInstance = cls.newInstance();
                beanMap.put(cls, pluginInstance);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

    /**
     * 注册job
     */
    public static void registerJob(Class<?> cls){

        if(BaseJob.class.isAssignableFrom(cls) && !cls.equals(BaseJob.class)){
            Object jobInstance;
            try {
                jobInstance = cls.newInstance();
                beanMap.put(cls, jobInstance);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

}
